<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vue的响应式原理</title>
</head>
<body>
  <!-- 
    1. app.message修改数据. Vue内部是如何监听message数据的改变
      Object.defineProperty -> 监听数据属性的改变
    2. 当数据发生改变, Vue 是如何知道要通知哪些人, 界面发生刷新
      发布订阅者模式
   -->
  <div id="app">
    <h5>{{message}}</h5>
  </div>
</body>
<script type="text/javascript">
  const obj = {
    message: '呵呵呵',
    name: 'why'
  };

  Object.keys(obj).forEach(key => {
    let value = obj[key];
    Object.defineProperty(obj, key, {
      set(newValue) {
        console.log('监听' + key + '改变');
        // 根据解析html代码，获取哪些人使用了该属性
        // 向使用了该变量的组件发送变量改变事件
        value = newValue;

        dep.notify();
      },
      get() {
        console.log('获取' + key + '对应的值' + value);
        dep.addSub(w1);
        return value;
      }
    })
  });

  // 发布者/订阅者模式
  class Dep {
    constructor() {
      this.subscribes = []
    }

    addSub(e) {
      if (!this.subscribes.find(w => w.name === e.name)) {
        this.subscribes.push(e);
      }
    }

    notify() {
      this.subscribes.forEach(w => w.update());
    }
  }

  class Watcher {
    constructor(name) {
      this.name = name;
    }

    update() {
      console.log(name + '发生update');
    }
  }

  const dep = new Dep();
  const w1 = new Watcher('张三');
  dep.addSub(w1);
</script>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '哈哈哈'
    }
  });
</script>
</html>